/*
 * Copyright (c) 2006, 2023, webrx.cn All rights reserved.
 *
 */
package cn.webrx.interceptor;

import cn.webrx.utils.SnowFlakeUtils;
import org.apache.ibatis.executor.parameter.ParameterHandler;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;

/**
 * <p></p>
 * <p>Powered by webrx On 2023-04-20 17:56:39</p>
 *
 * @author webrx [webrx@126.com]
 * @version 1.0
 * @since 17
 */

@Intercepts({
        @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class KeyGen implements Interceptor {

    SnowFlakeUtils su;

    public void setSu(SnowFlakeUtils su){
        this.su=su;
    }


    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object target = invocation.getTarget();
        MetaObject metaObject = SystemMetaObject.forObject(target);
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
        if (mappedStatement.getSqlCommandType() == SqlCommandType.INSERT) {

            ParameterHandler parameterHandler = (ParameterHandler)metaObject.getValue("delegate.parameterHandler");
            Object param = parameterHandler.getParameterObject();
            //System.out.println(param);
            //System.out.println(param.getClass().getDeclaredFields().length);

            //bigint long  long id; @AutoID
            try{
                if(param.getClass().getDeclaredField("id").isAnnotationPresent(AutoID.class)){
                    //String sql = metaObject.getValue("delegate.boundSql.sql").toString();
                    //String sql1 = sql.replace("null",String.valueOf(su.nextId()));
                    //metaObject.setValue("delegate.boundSql.sql", sql1);
                    Class<?> c = param.getClass();
                    Method method = c.getMethod("setId",Long.class);
                    method.invoke(param,su.nextId());
                    //System.out.println(param);
                }
            }catch(Exception e){
                e.printStackTrace();
            }
        }
        Object obj = invocation.proceed();
        return obj;
    }
}
